package sbc.jms.client;

import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import java.util.Properties;

import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueConnectionFactory;
import javax.jms.QueueSender;
import javax.jms.QueueSession;
import javax.jms.Session;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.xvsm.api.core.Capi;
import org.xvsm.api.core.ContainerRef;
import org.xvsm.api.core.CoordinationTypes;
import org.xvsm.api.core.Entry;
import org.xvsm.api.core.Tuple;
import org.xvsm.api.core.notification.NotificationID;
import org.xvsm.api.core.notification.NotificationListener;
import org.xvsm.client.ClientCapi;

import sbc.ejb3.dao.TimerRemote;
import sbc.model.Platine;
import sbc.model.Sensor;
import sbc.ms.Consumer;
import sbc.ms.Util;

/**
 * Bridge
 * 
 * Listens for Mozart Space Notifications
 * Starts TimerBean
 * Sends Platinen and Sensoren to bridgeQueue
 */
public class Bridge extends Thread implements NotificationListener {
	
	public static void main(String args[])	{
		if (args.length != 1) {
			System.out.println("URL needed!");
			System.out.println("Usage: java -cp <classpath> sbc.jms.client.Bridge http://localhost:8080/xvsm/xvsm");
			System.exit(1);
		}
		Bridge mybridge = new Bridge(args[0]);
		mybridge.start();
	}    
	
    private String url;
    private Capi capi;
    private ContainerRef cref;
    private List<Entry> elements;
    private InitialContext ctx;
	
	public Bridge (String url) {
		this.url = url;
		
		System.out.println ("Bridge @ " + url + " init");
		
		/*
		 * Mozart Space init
		 */
		try	{	
			/*
			 * get Mozart Space Container
			 */
			this.capi = new ClientCapi(url);
			this.capi.init(false);
			this.cref = Util.getOrCreateNamedContainer(capi, "Container", CoordinationTypes.FIFO);
			
			/*
			 * take every tupel out of Mozart Space
			 */
			//Taker taker = new Taker(capi, cref);
			//taker.start();
			
			addListener(this);
			
			System.out.println("Bridge constructed");
		}
		catch (Exception e)	{
			System.out.println("e: " + e);
		}	
		
		/*
		 * JBoss init
		 */
		Properties properties = new Properties();
		try {
	    	properties.load(new FileInputStream("resources/jndi.properties"));

		} 
		catch (IOException ioe) {
			System.out.print("error while loading properties - setting 'em manually");
			properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
			properties.put(Context.URL_PKG_PREFIXES, "org.jnp.interfaces");
			properties.put(Context.PROVIDER_URL, "localhost");
		}			
		try {
			System.out.println("Looking up InitialContext");
			ctx = new InitialContext(properties);
			
			System.out.println("Starting Timer Service");
			TimerRemote timerRemote = (TimerRemote) ctx.lookup("TimerBean/remote");
			timerRemote.scheduleTimerBean(0L, 0L);
		} 
		catch (NamingException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public void run() {
		System.out.println("Bridge up and running");
	}
	
	@SuppressWarnings("deprecation")
	public void sendNotification(NotificationID id, List<Entry> entries) {
		System.out.println("Bridge Notification fired: " + id + " - " + entries);
		
		/*
		 * get Platine/Sensor out ouf fired Entries
		 */
		Tuple t = (Tuple) entries.get(0);
		elements = t.getValue();	
		String type = elements.get(0).getValue().toString();	
		String name = elements.get(1).getValue().toString();
		
		System.out.println("type: " + type);		
		System.out.println("name: " + name);
		
		try	{			 
			/*
			 * connect to JMS Queue
			 * and send platine/sensor
			 */				
			System.out.println("Looking up queue");
			Queue queue = (Queue) ctx.lookup("queue/bridgeQueue");
	    	
	        System.out.println("Looking up connection factory");
			QueueConnectionFactory queueConnectionFactory = (QueueConnectionFactory) ctx.lookup("QueueConnectionFactory");
			
			System.out.println("Creating connection");
			QueueConnection connection = queueConnectionFactory.createQueueConnection();

	        try {
	           System.out.println("Creating session");
	           QueueSession session = connection.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);
	           
	           System.out.println("Creating sender");
	           QueueSender sender = session.createSender(queue);   

	           System.out.println("Starting connection");
	           connection.start();

	           System.out.println("Creating message");
	           ObjectMessage objectMessage = null;
	           if (type.equals("Platine")) {
	        	   objectMessage = session.createObjectMessage(new Platine(name));		      	   
	           }
	           else {
	        	   objectMessage = session.createObjectMessage(new Sensor(name));
	           }
	           
	           System.out.println("Sending message");
	           sender.send(objectMessage);	  
	        }
	        finally {
	        	connection.close();
		    } 			

	        System.out.println("writing data to queue: ok"); 
		}
        catch (Exception e) {
        	e.printStackTrace();
        }
	}
	
	public void sendNotification(NotificationID id) {
		System.out.println("Bridge Notification fired: " + id);
	}
	
	public void addListener(NotificationListener listener) {
		System.out.println("addListener");
		Consumer c = new Consumer(url, listener);
		c.start();
	}
}